package main

import (
	"flag"
	"fmt"
	"os"
	"os/signal"
	"regexp"
	"runtime"
	"strings"
	"syscall"

	"gitee.com/doraemon1996/bunny/log"
)

const (
	Mode_Server = "server"
	Mode_Client = "client"
)

var (
	Mode          = flag.String("Mode", "Server", "代码运行模式")
	LogFilePath   = flag.String("LogFilePath", "", "日志文件路径")
	LogLevel      = flag.String("LogLevel", "Info", "日志等级")
	Address       = flag.String("Address", "", "服务端地址")
	WSPath        = flag.String("WSPath", "", "Websocket 路径")
	WSSCertPath   = flag.String("WSSCertPath", "", "Websocket TLS 证书路径")
	WSSKeyPath    = flag.String("WSSKeyPath", "", "Websocket TLS 密钥路径")
	ClientCount   = flag.Uint64("ClientCount", 1, "客户端协程个数")
	MessageRepeat = flag.Uint64("MessageRepeat", 1, "客户端消息复制倍数")
)

func main() {
	// log.SetReportCaller(true)
	log.SetLevel(log.Level_Debug)

	flag.Parse()
	log.Infoln(flag.Args())

	FileLog(*LogFilePath, *LogLevel)

	network, address, err := ParseAddress(*Address)
	if err != nil {
		log.Fatalf("parse address %s failed. err: %v", *Address, err)
	}

	switch strings.ToLower(*Mode) {
	case Mode_Server:
		log.Info("-----------------Start Server----------------")
		RunServer(network, address, *WSPath, *WSSCertPath, *WSSKeyPath)
		Signaler()
		log.Info("-----------------Stop Server----------------")

	case Mode_Client:
		log.Info("-----------------Start Client----------------")
		RunClient(network, address, *WSPath, *WSSCertPath, *WSSKeyPath, *ClientCount, *MessageRepeat)
		Signaler()
		log.Info("-----------------Stop Client----------------")

	default:
		log.Errorf("unsupport launch mode: %v", *Mode)
	}

	Exit()
}

func ParseAddress(str string) (network, address string, err error) {
	adddressReg := regexp.MustCompile(`^\w+://[\w\d\.:\[\]]+$`)
	if !adddressReg.MatchString(str) {
		err = fmt.Errorf("%s regular match failed", str)
		return
	}

	list := strings.Split(str, "://")
	network = strings.ToLower(list[0])
	address = strings.ToLower(list[1])

	return
}

func Exit() {
	log.Infof("the process is about to exit")

	log.Exit(0)
}

func Signaler() {
	sigChan := make(chan os.Signal, 1)
	signal.Notify(sigChan, syscall.SIGTERM, syscall.SIGQUIT, syscall.SIGINT)
	sig := <-sigChan
	log.Infof("receive signal %v", sig)
}

type MemInfo struct {
}

func (mem *MemInfo) PrintMemInfo() {
	stats := runtime.MemStats{}
	runtime.ReadMemStats(&stats)
	log.Infof("memoery usage: %v MB", stats.Alloc/(1<<20))
}
